#include "ai_speech.h"
#include <sstream>

using namespace std;

// 在文件顶部或末尾添加
constexpr std::chrono::seconds AiSpeech::TIMEOUT_DURATION;

AiSpeech::AiSpeech(const string soundDevice) : soundDevice(soundDevice)
{
    // 初始化语音活动检测(VAD)参数
    const string resource_filename = "../resources/common.res";
    const float audio_gain = 1.0f;     // 音频增益设置为1.0（不放大）
    const bool apply_frontend = false; // 不应用前端处理

    /*
     * 初始化语音活动检测器(SnowboyVad)
     * 参数:
     *   resource_filename - 资源文件路径
     */
    detector_ = new snowboy::SnowboyVad(resource_filename);
    detector_->SetAudioGain(audio_gain);      // 设置音频增益
    detector_->ApplyFrontend(apply_frontend); // 设置是否应用前端处理

    /*
     * 获取音频参数
     */
    // int sample_rate = detector_->SampleRate();
    // int channels = detector_->NumChannels();
    // int bits_per_sample = detector_->BitsPerSample();
    // cout << "Audio Parameters:" << endl
    //      << "  Sample Rate: " << sample_rate << endl
    //      << "  Channels: " << channels << endl
    //      << "  Bits Per Sample: " << bits_per_sample << endl;

    // 初始化热词检测参数
    const string model_str = "../resources/models/nh1.pmdl,../resources/models/nh2.pmdl"; // 热词模型文件
    const float audio_gain_detect = 1.0f;                                                 // 音频增益
    const bool apply_frontend_detect = false;                                             // 不应用前端处理
    const string sensitivity_str = "0.5,0.5";                                             // 检测灵敏度

    /*
     * 初始化热词检测器(SnowboyDetect)
     * 参数:
     *   resource_filename - 资源文件路径
     *   model_str - 热词模型文件路径
     */
    hotword_detector_ = new snowboy::SnowboyDetect(resource_filename, model_str);
    hotword_detector_->SetSensitivity(sensitivity_str);      // 设置检测灵敏度
    hotword_detector_->SetAudioGain(audio_gain_detect);      // 设置音频增益
    hotword_detector_->ApplyFrontend(apply_frontend_detect); // 设置前端处理

    // 输出热词数量用于调试
    // const int hotwords_count = hotword_detector_->NumHotwords();
    // cout << "Initialized hotword detector with " << hotwords_count
    //      << " hotwords" << endl;
}

AiSpeech::~AiSpeech()
{
    // 释放语音活动检测器资源
    if (detector_ != nullptr)
    {
        delete detector_;
        detector_ = nullptr; // 避免悬空指针
    }

    // 释放热词检测器资源
    if (hotword_detector_ != nullptr)
    {
        delete hotword_detector_;
        hotword_detector_ = nullptr; // 避免悬空指针
    }

    if (recorder != nullptr)
    {
        delete recorder;
        recorder = nullptr;
    }
}

bool AiSpeech::Start()
{
    // 音频设备配置参数
    const std::string &device = soundDevice;                      // 使用引用避免拷贝
    constexpr unsigned int sample_rate = 16000;                   // 16kHz采样率标准
    constexpr int channels = 1;                                   // 单声道录制
    const snd_pcm_format_t format = AlsaRecorder::DEFAULT_FORMAT; // 默认音频格式
    const int duration = 1;                                       // 默认录制时长
    const std::string &filename = AlsaRecorder::DEFAULT_FILENAME; // 默认存储路径

    try
    {
        // 初始化ALSA录音设备
        // 参数说明：
        // device - 音频设备名称
        // sample_rate - 采样率
        // channels - 声道数
        // format - 音频格式
        // duration - 录制时长(ms)
        // filename - 存储文件路径
        recorder = new AlsaRecorder(device, sample_rate, channels,
                                    format, duration, filename);

        if (recordThread == nullptr)
        {
            recordThreadFlag.store(true);
            recordThread = new thread(&AiSpeech::recordAudioThreadFunc, this);
        }

        return true; // 成功启动返回true
    }
    catch (const std::exception &e)
    {
        // 记录完整的错误日志
        std::cerr << "[音频系统错误] " << e.what() << std::endl;

        // 重新抛出异常（允许上层调用者处理）
        throw std::runtime_error(std::string("音频子系统错误: ") + e.what());
    }

    // 保留仅作为防御性编程
    return false;
}

void AiSpeech::stop()
{
    if (recordThread && recordThread->joinable()) // 2. 检查线程是否存在且可join
    {
        recordThreadFlag.store(false); // 1. 设置标志位，通知线程退出
        recordThread->join();          // 3. 等待线程结束
        delete recordThread;
        recordThread = nullptr; // 避免悬空指针
    }
}

#define RECODE_TIME_MS 300

void AiSpeech::recordAudioThreadFunc()
{
    vector<uint8_t> rdata;
    string apiKey = "Aox60I9WAoQNuMgq7cAZywLf";
    string secretKey = "F2BCeISSX9g9PU523XZp6YSmDkLB7wrC";
    BaiduAiAsr baidu_asr(apiKey, secretKey);

    while (recordThreadFlag.load())
    {
        if (!recorder->record(rdata))
        {
            stop();
            break;
        }
        if (detector_->RunVad((int16_t *)rdata.data(), rdata.size() / 2) < 0)
        {
            if (!userSpeechData.empty())
            {
                // 检测到静音且已有录音数据，处理录音数据
                recognizeUserSpeechAudio(baidu_asr, userSpeechData);
            }
            // 静音状态：检查是否超时
            auto now = std::chrono::steady_clock::now();

            if (isFirst == 1 && (now - lastActiveTime > TIMEOUT_DURATION))
            {
                isFirst = 0;
                cout << "[静音超时] 规定时间内无有效输入" << endl;
            }
            continue;
        }

        userSpeechData.insert(userSpeechData.end(), rdata.begin(), rdata.end());
    }
}

void AiSpeech::recognizeUserSpeechAudio(const std::vector<uint8_t> &audioData)
{
    uint32_t ret = hotword_detector_->RunDetection((int16_t *)audioData.data(), audioData.size() / 2);
    if (ret > 0)
    {
        system("aplay ../resources/audio/hy.wav &");
    }

    userSpeechData.clear();
}

void AiSpeech::recognizeUserSpeechAudio(BaiduAiAsr &baidu_asr, const vector<uint8_t> &audioData)
{
    if (audioData.empty())
        return;

    string res = baidu_asr.speechRecognition(audioData);

    if (res.empty())
    {
        userSpeechData.clear();
        cout << "未识别到有效结果" << endl;
        return;
    }
    if (res == "你好。" && isFirst == 0)
    {
        isFirst = 1;
        system("aplay ../resources/audio/hy.wav &");
    }
    if (isFirst == 1)
    {
        cout << "识别结果: " << res << endl;
        lastActiveTime = std::chrono::steady_clock::now(); // 仅更新活跃时间
    }

    userSpeechData.clear();
}
